<?php


namespace yy\auth;


use tauthz\facade\Enforcer;
use think\facade\Db;
use yy\helper\PHPTree;

class Permissions
{

    protected static $instance;
    protected $user;
    protected $userPrev = 'u-';
    protected $role;
    protected $rolePrev = 'r-';
    protected $permission;
    protected $obj;
    protected $action;
    protected $projectId = 35;

    // private function __construct($user, $role, $permission)
    // {
    //     $this->setUser($user);
    //     $this->setRole($role);
    //     $this->setPermission($permission);
    // }

    public static function init($user = null, $role = null, $permission = null)
    {
        if (is_null(self::$instance)) {
            self::$instance =  new static();
        }
        self::$instance->setUser($user);
        self::$instance->setRole($role);
        self::$instance->setPermission($permission);
        return self::$instance;


    }

    /**
     * 权限结点列表
     */
    public function getList()
    {
        $return = Db::table('permissions')
            ->select()
            ->toArray();
        array_walk($return, function (&$v) {
            $v['path'] = strtolower($v['path']);
        });
        return PHPTree::makeTree($return);

    }


    /**
     * 添加角色权限
     */
    public function addPermissionForRole()
    {

        return Enforcer::addPolicy($this->role, $this->obj, $this->action);
    }

    /**
     * 取角色所有权限
     * @return array 接口地址数组
     */
    public function getPermissionsForRole()
    {
        // halt($this->role);
        $list =  Enforcer::getPermissionsForUser($this->role);
        // halt($list);
        return array_map(function ($v) {
            return $this->permission2url($v);
        }, $list);
    }

    /**
     * 删除角色权限
     * @return mixed
     */
    public function deletePermissionsForRole()
    {
        return Enforcer::deletePermissionForUser($this->role, $this->obj, $this->action);
    }

    /**
     * 删除角色
     * @return mixed
     */
    public function deleteRole()
    {
        Enforcer::deleteRole($this->role);

    }

    /**
     * 取所有角色
     * @return array 角色id 数组
     */
    public function getAllRoles()
    {
        $list = Enforcer::getAllRoles();
        return array_map(function ($v) {
            return (int) str_replace($this->rolePrev , '' , $v);
        } , $list);

    }

    /**
     * 添加用户角色
     */
    public function addRoleForUser()
    {
        Enforcer::addRoleForUser($this->user, $this->role);

    }


    /**
     * 取用户的所有角色
     * @return array 角色id 数组
     */
    public function getRolesForUser()
    {
        $list = Enforcer::getRolesForUser($this->user);
        // halt($list);
        return array_map(function ($v) {
            return (int) str_replace($this->rolePrev , '' , $v);
        } , $list);
    }

    /**
     * 删除用户角色
     * @return mixed
     */
    public function deleteRoleForUser()
    {
        return Enforcer::deleteRoleForUser($this->user, $this->role);
    }

    /**
     * 删除用户所有角色
     * @return mixed
     */
    public function deleteAllRolesForUser()
    {
        return Enforcer::deleteRolesForUser($this->user);
    }

    /**
     * 判断是否有权限
     * @return mixed
     */
    public function hasPermission()
    {
        if (!$this->checkExistPermission()) return true;
        // halt($this->user , $this->obj , $this->action);
        return Enforcer::enforce($this->user, $this->obj, $this->action);

    }

    public function checkPermissionForUrl()
    {
        $url = request()->baseUrl();
        $this->setPermission($url);
        return $this->hasPermission();

    }

    /**
     * 取所有权限结点
     * @return mixed
     */
    private function getAllPermissions()
    {
        $results = Enforcer::getPolicy();
        array_map(function ($v) use (&$permissions) {
            $permissions[] = '/' . $v[1] . '/' . $v[2];
        }, $results);
        return $permissions;

    }

    /**
     * 路径转权限
     * @param $permission
     */
    private function setPermission($permission)
    {
        if (empty($permission)) return;
        $permission = strtolower($permission);
        $permission       = trim($permission, '/');
        $permission       = str_replace(["\\", "/"], "|", $permission);
        $list = explode("|", $permission);
        $this->obj = $list[0] ;
        $this->action = $list[1];
        if (!empty($list[2]))$this->action .= '-' . $list[2];
        $this->permission = '/' . $this->obj .'/' . $this->action;
    }

    private function permission2url($permission){
        if (strpos($permission['2'] , '-') !== false){
            $permission[2] = str_replace('-' , '/' , $permission['2']);
        }
        return '/' . $permission['1'] . '/' . $permission[2];
    }

    /**
     * 角色转换
     * @param $role
     */
    private function setRole($role)
    {
        $this->role = $this->rolePrev . $role;
    }

    /**
     * 用户转换
     * @param $user
     */
    private function setUser($user)
    {
        $this->user = $this->userPrev . $user;
    }

    /**
     * 判断当前权限是否加到权限组里
     * @return bool true 存在 FALSE 不存在
     */
    private function checkExistPermission()
    {
        return in_array($this->permission, $this->getAllPermissions());
    }

    /**
     * 从myapi 导入权限结点
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function seed()
    {
        Db::query("truncate TABLE permissions");
        $result = Db::connect('myApi')
            ->table('api')
            ->where('projectId', '=', $this->projectId)
            ->select();
        foreach ($result as $item) {
            $arr = [
                'id'        => $item['id'],
                'parent_id' => $item['parentId'],
                'name'      => $item['name'],
                'path'      => $item['apiUrl'],
                'view_sort' => $item['order'],
            ];
            if ($arr['path'] == '/captcha') continue;
            $insert[] = $arr;

        }
        Db::table('permissions')
            ->delete(true);
        Db::table('permissions')
            ->insertAll($insert);
        $this->initPermission();
    }

    /**
     * 初始化权限 添加管理员所有权限
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function initPermission()
    {
        $roles = $this->getAllRoles();
        array_map($this->deleteRole(), $roles);
        $this->setRole('1');
        \app\facade\Roles::initAdmin();
        Db::query("truncate TABLE rules");
        Db::table('permissions')
            ->where('path', '<>', '')
            ->select()
            ->each(function ($rt) {
                $this->setPermission($rt['path']);
                $this->addPermissionForRole();
            });
    }

    public function getPermissionsForUser()
    {
        $roles = $this->getRolesForUser();
        if (empty($roles))return[];
        $permissions = [];
        foreach ($roles as $role){
            $this->setRole($role);
            $permissions = array_merge($permissions ,$this->getPermissionsForRole());
        }

        return $permissions;
    }

}